package xyz.lwm.lazycat.annotation;

import xyz.lwm.lazycat.beans.BeanDesign;
import xyz.lwm.lazycat.beans.Condition;
import xyz.lwm.lazycat.utility.StringUtil;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author lwm
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Conditional(ConditionalOnMissingBean.MissingBeanCondition.class)
public @interface ConditionalOnMissingBean {

    /**
     * Bean name, 优先匹配 name
     */
    String name() default "";

    /**
     * Bean class
     */
    Class<?> value() default Void.class;

    /**
     * on missing bean 条件判断
     */
    class MissingBeanCondition implements Condition {

        @Override
        public boolean matches(Context ctx, BeanDesign<?> design) {

            ConditionalOnMissingBean onMissingBean = design.getAnnotations()
                    .getAnnotation(ConditionalOnMissingBean.class);
            String name = onMissingBean.name();
            Class<?> clz = onMissingBean.value();
            if (clz == Void.class || clz == Object.class) {
                clz = design.getType();
            }
            if (StringUtil.isNotBlank(name)) {
                return !ctx.getDesignMap().containsKey(name);

            } else {
                final Class<?> beanType = clz;
                return ctx.getDesignMap().values().stream().noneMatch(d ->
                        beanType.isAssignableFrom(d.getType()));

            }

        }

    }

}
